﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ServerLib;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Messaging;

namespace ChatClient
{
    public partial class ChatForm : Form
    {
        private IRemoteServer remserv;// A remote object for the server
        private ClientInfo clientinfo;// Structur where stored information of current user
        private Login lrf;// Form for login to chat
        private System.Timers.Timer _timer;// timer for chacking number of users online;
        private ChatEventSink _eventSink;// object of specified class to help transfering information
        
        /// <summary>
        /// Form constror
        /// </summary>

        public ChatForm()
        {
            //Setting of Remotig configuration using the configuration file
            RemotingConfiguration.Configure(@"ChatClient2.exe.config");

            InitializeComponent();

            remserv = (IRemoteServer)new RemoteServer();//initialization of remote object
            _eventSink = new ChatEventSink();//initialization of EventSinkClass
            lrf = new Login(remserv);//initialization of Login form
            lrf.LoginEvent += GetLoginedClient;
            _eventSink.EventSinkEvent += this.GenerateMessage;
            remserv.ChatEvent += _eventSink.SubmissionCallback;
            _timer = new System.Timers.Timer();
            _timer.Interval = 500;
        }

        //before chat-form is loading, opens form of login 
        private void ChatForm_Load(object sender, EventArgs e)
        {
            lrf.ShowDialog();

            if (lrf.DialogResult == System.Windows.Forms.DialogResult.Cancel)
            {
                this.Close();
            }
        }

        private void logoutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _timer.Stop();
            remserv.RemoveClient(clientinfo.Login);
            this.Hide();
            this.ShowDialog();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnClose();
            this.Close();
        }

        private void buttonSend_Click(object sender, EventArgs e)
        {
            if (textBoxSend.Text.TrimEnd() != "")
            remserv.AddMessage(clientinfo.Login, this.textBoxSend.Text);
            textBoxSend.Text = "";
        }

        /// <summary>
        /// Gets information about logined client and check list of logined clients
        /// </summary>
        /// <param name="clinfo"></param>

        private void GetLoginedClient(ClientInfo clinfo)
        {
            clientinfo = clinfo;
            labelNameShow.Text = clientinfo.Name;
            labelLastNameShow.Text = clientinfo.LastName;
            labelBirthDateShow.Text = clientinfo.Birthday;
            labelSexShow.Text = clientinfo.Sex.ToString();
            _timer.Elapsed += GetServerData;
            _timer.Start();
        }

        /// <summary>
        /// Check the list of logined users and show it to client im listView
        /// </summary>
        /// <param name="sendler"></param>
        /// <param name="e"></param>
        /// 
        private void GetServerData(Object sendler, System.Timers.ElapsedEventArgs e)
        {
            ArrayList _list = remserv.GetListOfClients();
            listView1.Invoke(new Action(() =>
            {
                this.listView1.Items.Clear();
            }));
            foreach (string name in _list)
            { 
                listView1.Invoke(new Action(() => 
                {
                    this.listView1.Items.Add(name);
                }));
            }
        }

        /// <summary>
        /// Removes client from list of logined users
        /// </summary>
 
        private void OnClose()
        {
            remserv.RemoveClient(clientinfo.Login);
        }

        private void ChatForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            OnClose();
        }

        private void buttonSetNewData_Click(object sender, EventArgs e)
        {
            string BirthDate;
            String login = clientinfo.Login;
            DateTime dt = dateTimePicker1.Value;
            BirthDate = dt.Year + "-" + dt.Month + "-" + dt.Day;

            remserv.SetUserInfo(clientinfo.Login, textBoxName.Text,
                textBoxLastName.Text, BirthDate, 
                radioButton1.Checked == true ? ClientInfo.EnumSex.Male : ClientInfo.EnumSex.Female);
            MessageBox.Show("Data is updated");
            clientinfo = remserv.GetClientInfo(login);
            labelNameShow.Text = clientinfo.Name;
            labelLastNameShow.Text = clientinfo.LastName;
            labelBirthDateShow.Text = clientinfo.Birthday;
            labelSexShow.Text = clientinfo.Sex.ToString();
            textBoxName.Text = "";
            textBoxLastName.Text = "";
        }

        private void buttonChangePassword_Click(object sender, EventArgs e)
        {
            if (remserv.CheckPassword(clientinfo.Login, textBoxOldPassword.Text)
                && textBoxNewPassword.Text == textBoxConfirm.Text)
            {
                remserv.ChangePassword(clientinfo.Login, textBoxNewPassword.Text);
                textBoxConfirm.Text = "";
                textBoxOldPassword.Text = "";
                textBoxNewPassword.Text = "";
                MessageBox.Show("Password is chenged!!!");
            }
            else
            {
                MessageBox.Show("Old password is wrong, or new password and confirmation not are the same");
            }

        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            if (remserv.CheckPassword(clientinfo.Login, textBoxPasswordForDelete.Text))
            {
                remserv.RemoteUser(clientinfo.Login, textBoxPasswordForDelete.Text);
                _timer.Stop();
                remserv.RemoveClient(clientinfo.Login);
                this.Hide();
                this.ShowDialog();
            }
            else
            {
                MessageBox.Show("Password is wrong");
            }
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ClientInfo currentUser;
            String strInfo;
            String strSelLogin = "";
            foreach (ListViewItem item in this.listView1.SelectedItems)
            {
                strSelLogin = item.Text;
            }
            currentUser = remserv.GetClientInfo(strSelLogin);
            strInfo = "Name : " + currentUser.Name + Environment.NewLine;
            strInfo += "LastName : " + currentUser.LastName + Environment.NewLine;
            strInfo += "Birthday : " + currentUser.Birthday + Environment.NewLine;
            strInfo += "Sex : " + currentUser.Sex.ToString() + Environment.NewLine;
            strInfo += "Login : " + currentUser.Login + Environment.NewLine;
            MessageBox.Show(strInfo);
        }

        /// <summary>
        /// Ganaretes new massege on users screen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void GenerateMessage(Object sender, ChatEventArgs e)
        {
            this.listBoxChatForm.Invoke(new Action(() =>
            {
                this.listBoxChatForm.Items.Add(e.Login + " : " + e.Message);
                this.listBoxChatForm.SelectedIndex = this.listBoxChatForm.Items.Count - 1;
            }));
        }
    }

    public delegate void EventSinkEventHandler(Object sender, ChatEventArgs e);

    /// <summary>
    /// utility class to transfer information
    /// </summary>

    public class ChatEventSink : RemotelyDelegatableObject
    {
        public ChatEventSink()
            : base()
        { }

        public override object InitializeLifetimeService()
        {
            return null;
        }

        protected override void InternalSubmissionCallback(object sender, ChatEventArgs e)
        {
            if (EventSinkEvent != null)
            {
                EventSinkEvent(this, e);
            }
        }

        public event EventSinkEventHandler EventSinkEvent;
    }
}
